// Copyright (C) 2010  Joan Puigcerver Perez, <joapuipe@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

/**
 * \mainpage The Oracle of Woody Allen
 *
 * \section usage Usage
 * 
 * Use the command <i>oracle</i> to launch the server. 
 * Use the option <i>-log logfile</i> to save the logs produced by
 * the program to the file logfile.
 * 
 * This program listens on the port 4242 by default.
 * The requests that arrive to this port will be processed and
 * a response will be send to the connected client.
 *
 * \section webpage Web page
 * 
 * A web based client is available at:
 *
 * http://www.jpuigcerver.net/allen 
 *
 * This is the official web page of The Oracle of Woody Allen. 
 * There you can test the full functionalities of the program and learn
 * how the program internally works.
 *
 * \section source Source code
 *
 * The source code is fully available at:
 *
 * http://code.google.com/p/oracleofwoodyallen
 *
 * \section license License
 * Copyright (C) 2010  Joan Puigcerver Perez, <joapuipe@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <iostream>
#include <clocale>

#include <TCPServer.hpp>
#include <TCPClientSession.hpp>
#include <Database.hpp>

using namespace std;
using namespace ost;

int main(int argc, char ** argv) {
  ostream * logfile = &cout;

  setlocale(LC_ALL, "ca_ES.utf8");
  setlocale(LC_MESSAGES, "ca_ES.utf8");
  setlocale(LC_CTYPE, "ca_ES.utf8");

  for(int arg = 1; arg < argc; ++arg) {
    if ( !strcmp(argv[arg], "--log") && arg+1 < argc ) {
      logfile = new ofstream();
      ((ofstream*)logfile)->open(argv[arg+1], ios::app);
      if ( !((ofstream*)logfile)->is_open() ) {
	cout << argv[arg+1] << " couldn't been opened!" << endl;
	delete logfile;
      }
      ++arg;
    } else {
      cout << "Usage: " << argv[0] << " [options]" << endl;
      cout << "Valid options: " << endl;
      cout << "  --help\t shows this help." << endl;
      cout << "  --log file\t sets the log file." << endl;
      return 0;
    }
  }

  try {
    XMLPlatformUtils::Initialize();
  }
  catch( const XMLException & toCatch ) {
    char* message = XMLString::transcode(toCatch.getMessage());
    print_log_line("Error during initialization! :", *logfile, LOGmutex);
    print_log_line("Exception message is:", *logfile,LOGmutex);
    print_log_line(message, *logfile, LOGmutex);
    XMLString::release(&message);
    return 0;
  }

  print_log_line("Oracle is running!", (*logfile));

  Database database( *logfile, LOGmutex );
  database.load();

  TCPClientSession * tcp;
  IPV4Address addr(0, 0);
  TCPServer server(addr, 4242, *logfile);
  
  try {
    while(server.isPendingConnection()) {
      tcp = new TCPClientSession(&database, server, 10000, *logfile);
      tcp->detach();
    }
  }
  catch(Socket *socket) {
    tpport_t port;
    int err = socket->getErrorNumber();
    InetAddress saddr = (InetAddress)socket->getPeer(&port);
    char err_msg[50];
    sprintf(err_msg, "socket error %s:%u = %d", saddr.getHostname(), port, err);
    print_log_line(err_msg, (*logfile));
    if(err == Socket::errBindingFailed) {
      print_log_line("bind failed; port busy", (*logfile));
      return 1;
    }
    else
      print_log_line("client socket failed", (*logfile));
  }

  if ( logfile != &cout ) {
    ((ofstream*)logfile)->close();
    delete logfile;
  }
  XMLPlatformUtils::Terminate();
  return 0;
}
